package com.netty.pro.netty.nio.GroupChat;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;

/**
 * @author xuzn
 * @ClassName: GroupServer
 * @ProjectName echo-project
 * @date 2020/3/8/16:48
 */
public class GroupServer {
  private Selector selector;
  private ServerSocketChannel listenChannel;
  private static final int PORT = 6666;

  public GroupServer() {
    try {
      // 创建selector
      selector = Selector.open();
      // 创建channel
      listenChannel = ServerSocketChannel.open();
      // 绑定端口
      listenChannel.socket().bind(new InetSocketAddress(PORT));
      // 设置非阻塞
      listenChannel.configureBlocking(false);
      // 将listenChannel注册到selector上
      listenChannel.register(selector, SelectionKey.OP_ACCEPT);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  public void listen() {
    System.out.println("监听的线程:" + Thread.currentThread().getName());
    try {
      while (true) {
        // 获取到有哪些事件发生
        int select = selector.select();
        if (select == 0) {
          System.out.println("服务端等待1秒");
          continue;
        }
        // 有事件的selectionKeys
        Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
        while (iterator.hasNext()) {
          SelectionKey key = iterator.next();
          // 监听到accept
          if (key.isAcceptable()) {
            SocketChannel sc = listenChannel.accept();
            sc.configureBlocking(false);
            // 将socketchannel注册到selector上
            sc.register(selector, SelectionKey.OP_READ);
            // accept事件,提示上线
            System.out.println(sc.getRemoteAddress() + "上线~");
          }

          if (key.isReadable()) {
            readData(key);
          }
          // 移除key,手动删掉key,避免重复操作
          iterator.remove();
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    } finally {

    }
  }

  public void readData(SelectionKey key) {
    SocketChannel channel = null;
    try {
      // 通过这个key找到相应的channel
      channel = (SocketChannel) key.channel();
      // 创建缓冲区
      ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
      int count = channel.read(byteBuffer);
      if (count > 0) {
        // 把缓冲区的数据转成字符串并输出
        String msg = new String(byteBuffer.array());
        System.out.println("from 客户端" + msg);
        // 向其他客户端转发消息
        sendInfoToOtherClients(msg, channel);
      }
    } catch (Exception e) {
      try {
        System.out.println(channel.getRemoteAddress() + "离线了...");
        key.cancel();
        channel.close();
      } catch (Exception e1) {
        e1.printStackTrace();
      }
    }
  }

  public void sendInfoToOtherClients(String msg, SocketChannel self) throws Exception {
    //
    System.out.println("服务器转发消息中...");
    System.out.println("服务器转发给客户端的线程是:" + Thread.currentThread().getName());
    for (SelectionKey key : selector.keys()) {
      Channel targetChannel = key.channel();
      // 排出自己
      if (targetChannel instanceof SocketChannel && targetChannel != self) {
        SocketChannel dest = (SocketChannel) targetChannel;
        // 将msg存储到buffer
        ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes());
        // 将buffer的数据写到通道
        dest.write(buffer);
      }
    }
  }

  public static void main(String[] args) {
    // 启动服务器端
    GroupServer groupServer = new GroupServer();
    groupServer.listen();
  }
}
